/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

package net.worlds.ui;

import java.awt.datatransfer.DataFlavor;
import java.awt.datatransfer.Transferable;
import java.awt.datatransfer.UnsupportedFlavorException;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import javax.swing.JComponent;
import javax.swing.JTree;
import javax.swing.SwingUtilities;
import javax.swing.TransferHandler;
import javax.swing.tree.DefaultMutableTreeNode;
import javax.swing.tree.DefaultTreeModel;
import javax.swing.tree.TreePath;
import net.worlds.Main;
import net.worlds.object.GameObject;


public class PartsTreeTransferHandler extends TransferHandler{
    DataFlavor nodesFlavor;
    DataFlavor[] flavors = new DataFlavor[1];
    DefaultMutableTreeNode[] nodesToRemove;
    public PartsTreeTransferHandler()
    {
        String mimeType = DataFlavor.javaJVMLocalObjectMimeType +
        ";class=\"" +
        PartTreeNode[].class.getName() +
        "\"";
        try {
            nodesFlavor = new DataFlavor(mimeType);
        } catch (ClassNotFoundException ex) {
            Main.error(ex);
        }
        flavors[0] = nodesFlavor;
    }
    @Override
    public boolean canImport(TransferHandler.TransferSupport support)
    {
        if(!support.isDrop())
            return false;
        JTree.DropLocation dropLocation = (JTree.DropLocation) support.getDropLocation();
        return dropLocation.getPath() != null;
    }
    private DefaultMutableTreeNode copy(DefaultMutableTreeNode node) {
        DefaultMutableTreeNode newNode = new DefaultMutableTreeNode(node);
        newNode.setUserObject(node.getUserObject());
        return newNode;

    }
    @Override
   protected Transferable createTransferable(JComponent c) {
    JTree tree = (JTree)c;
    TreePath[] paths = tree.getSelectionPaths();
        if(paths != null) {
            // Make up a node array of copies for transfer and
            // another for/of the nodes that will be removed in
            // exportDone after a successful drop.
            List<DefaultMutableTreeNode> copies =
            new ArrayList<DefaultMutableTreeNode>();
            List<DefaultMutableTreeNode> toRemove =
            new ArrayList<DefaultMutableTreeNode>();
            DefaultMutableTreeNode node =
            (DefaultMutableTreeNode)paths[0].getLastPathComponent();
            final DefaultMutableTreeNode copy = copy(node);
            copies.add(copy);
            toRemove.add(node);
            for(int i = 1; i < paths.length; i++) {
                final DefaultMutableTreeNode next =
                (DefaultMutableTreeNode)paths[i].getLastPathComponent();
                // Do not allow higher level nodes to be added to list.
                if(next.getLevel() < node.getLevel()) {
                        break;
                } else if(next.getLevel() > node.getLevel()) { // child node
                    SwingUtilities.invokeLater(new Runnable()
                    {

                        public void run() {
                            copy.add(copy(next));
                        }

                    });
                    // node already contains child
                } else { // sibling
                    copies.add(copy(next));
                    toRemove.add(next);
                }
            }
                DefaultMutableTreeNode[] nodes =
                copies.toArray(new DefaultMutableTreeNode[copies.size()]);
                nodesToRemove =
                toRemove.toArray(new DefaultMutableTreeNode[toRemove.size()]);
            return new NodesTransferable(nodes);
        }
    return null;
    }
    @Override
    protected void exportDone(JComponent source, Transferable data, int action) {

    }

    @Override
    public int getSourceActions(JComponent c) {
        return MOVE;
    }
    @Override
    public boolean importData(TransferHandler.TransferSupport support) {
        if(!canImport(support)) {
            return false;
        }
        DefaultMutableTreeNode[] nodes = null;
        try {
            Transferable t = support.getTransferable();
            nodes = (DefaultMutableTreeNode[])t.getTransferData(nodesFlavor);
        }
        catch(UnsupportedFlavorException ex)
        {
            Main.error(ex);
        }
        catch(IOException ex)
        {
            Main.error(ex);
        }
        JTree.DropLocation dl = (JTree.DropLocation)support.getDropLocation();
        int childIndex = dl.getChildIndex();
        TreePath dest = dl.getPath();
        DefaultMutableTreeNode parent =
        (DefaultMutableTreeNode)dest.getLastPathComponent();
        JTree tree = (JTree)support.getComponent();
        DefaultTreeModel model = (DefaultTreeModel)tree.getModel();
        int index = childIndex;
        if(childIndex == -1)
        {
            index = parent.getChildCount();
        }
        for(int i = 0; i < nodes.length; i++)
        {
            PartTreeNode pn = (PartTreeNode)nodes[i].getUserObject();
            final GameObject parentObj = ((PartTreeNode)parent).getObject();
            if(pn == parent)
                continue;
            if(parent.isNodeAncestor(pn))
                continue;
            if(pn.getParent() == Main.getGame().getCurrentWorld().getRootObject().getTreeNode())
                continue;
            final GameObject obj = pn.getObject();
            Main.runInMainThread(new Runnable()
            {
                public void run()
                {
                    try {
                        obj.setProp("Parent", parentObj, true);
                    } catch (Exception ex) {
                        throw new RuntimeException(ex);
                    }
                }
            });
        }
        return true;
    }
    public class NodesTransferable implements Transferable {
        DefaultMutableTreeNode[] nodes;

        public NodesTransferable(DefaultMutableTreeNode[] nodes)
        {
            this.nodes = nodes;
        }

        public Object getTransferData(DataFlavor flavor) throws UnsupportedFlavorException
        {
            if(!isDataFlavorSupported(flavor))
            throw new UnsupportedFlavorException(flavor);
            return nodes;
        }

        public DataFlavor[] getTransferDataFlavors()
        {
            return flavors;
        }

        public boolean isDataFlavorSupported(DataFlavor flavor)
        {
            return nodesFlavor.equals(flavor);
        }
    }
}
